#ifndef __TESTABLE__H__
#define __TESTABLE__H__

#if _MSC_VER > 1000
#pragma once
#endif


#include <assert.h>

#include "type.h"

namespace AllTing
{

namespace Test
{

using namespace AllTing;

class Testable;

typedef std::vector<Testable*>	Tests;
typedef std::vector<Testable*>::iterator		TestIterator;
typedef std::vector<Testable*>::const_iterator	TestConstIterator;

typedef struct tagASSERT_INFO
{
	String strFile;
	UInt32 nLine;
}ASSERT_INFO;

typedef std::vector<ASSERT_INFO> Asserts;
typedef std::vector<ASSERT_INFO>::const_iterator AssertConstIterator;

class Testable
{
protected:
	Testable(){}
public:
	Testable(const String& strName, const Bool bSelect=true, const Bool bStopOnFailed=false) : 
				strName_(strName), bSelected_(bSelect), bStopOnFailed_(bStopOnFailed), 
				nError_(0), nCurrentTime_(0), nElapsedTime_(0)
	{
	}
	Testable(const Char* pszName, const Bool bSelect=true, const Bool bStopOnFailed=false) : 
				strName_(pszName), bSelected_(bSelect), bStopOnFailed_(bStopOnFailed), 
				nError_(0), nCurrentTime_(0), nElapsedTime_(0)
	{
	}
	virtual ~Testable();

	Testable(const Testable& aTest)
	{
		strName_ = aTest.strName_;
		bSelected_ = aTest.bSelected_;
		nError_ = aTest.nError_;
		nCurrentTime_ = aTest.nCurrentTime_;
		nElapsedTime_ = aTest.nElapsedTime_;
		bStopOnFailed_ = aTest.bStopOnFailed_;
	}

	virtual Bool Run();
	virtual Bool SetUp();
	virtual Bool TearDown();

	void Select(Bool bSelect)
	{
		bSelected_ = bSelect;
	}

	UInt32	Error()
	{
		return nError_;
	}
	Bool	StopOnFailed()
	{
		return bStopOnFailed_;
	}
	Bool	Select()
	{
		return bSelected_;
	}
	bool operator ==(const Testable &T) const
	{
		return (strName_ == T.strName_ && 
				bSelected_ == T.bSelected_ && 
				nError_ == T.nError_ &&
				nCurrentTime_ == T.nCurrentTime_ &&
				nElapsedTime_ == T.nElapsedTime_ &&
				bStopOnFailed_ == T.bStopOnFailed_);
	}

	const Char* Name(){return strName_.c_str();}

	void		Error(const Char* pszFile, UInt32 nLine)
	{
		ASSERT_INFO ai;
		ai.strFile = pszFile;
		ai.nLine = nLine;

		aFailedAssert_.push_back(ai);
	}

	AssertConstIterator BeginFailedAssert()
	{
		return aFailedAssert_.begin();
	}
	AssertConstIterator EndFailedAssert()
	{
		return aFailedAssert_.end();
	}

	typedef int (Testable::*Testee)();
protected:
	String		strName_;
	Bool		bSelected_;
	Bool		bStopOnFailed_;
	UInt32		nError_;
	UInt32		nCurrentTime_;
	UInt32		nElapsedTime_;

	Asserts		aFailedAssert_;
};

}	//namespace Test

}	//namespace AllTing

#endif